package bl;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import util.Data;
import util.DefaultMessages;
import util.LeitorExtratoBB;
import util.RelatorioPrinter;
import cadastro.CadastroUsuarios;
import datamanager.Conta;
import datamanager.DataManager;
import datamanager.Entrada;
import datamanager.Gasto;
import exceptions.AtributoInvalidoException;
import exceptions.MyMoneyException;
import exceptions.UsuarioException;

public class MyMoneyManager {

	private static final String SEP = File.separator;
	
	private static final String GASTO_PREFIXO = "gasto";
	private static final String ENTRADA_PREFIXO = "entrada";
	private static final String CONTA_PREFIXO = "conta";
	
	private final String PERSISTENCIA_FILENAME = "persistencia.xml";
	private final String RELATORIOS_DIR = "saidaRelatorios"+SEP;
	private CadastroUsuarios cadastro;
	private Usuario usuarioLogado;
	private DataManager dManager;
	
	public MyMoneyManager() throws MyMoneyException {
		cadastro = new CadastroUsuarios(PERSISTENCIA_FILENAME);
		usuarioLogado = null;
		dManager = new DataManager();
	}

	public void zeraSistema() {
		cadastro.zeraCadastro();
	}

	public void cadastraUsuario(String nome, String senha, String email)
			throws MyMoneyException {
		if (emailValido(email)) {
			Usuario usuario = new Usuario(nome, senha, email);
			if (!ehUsuarioCadastrado(email)) {
				cadastro.cadastrar(usuario);
				cadastro.gravaCadastro();

			} else {
				throw new MyMoneyException(DefaultMessages.USER_JA_EXISTE_MSG);
			}
		} else {
			throw new MyMoneyException(DefaultMessages.INV_EMAIL_MSG);
		}
	}

	private boolean emailValido(String email) {
		String regex = ".+@.+\\.[a-z]+";
		if (Pattern.matches(regex, email)) {
			return true;
		}
		return false;
	}

	public boolean ehUsuarioCadastrado(String email) {
		return getUsuarioPorEmail(email) != null;
	}

	public Usuario getUsuarioPorEmail(String email) {
		return cadastro.buscaPorEmail(email);
	}

	public void login(String email, String senha) throws MyMoneyException {
		if (!emailValido(email)) {
			throw new AtributoInvalidoException(DefaultMessages.INV_EMAIL_MSG);
		}
		if (ehUsuarioCadastrado(email)) {
			Usuario aLogar = getUsuarioPorEmail(email);

			if (aLogar.getSenha().equalsIgnoreCase(senha)) {
				System.out.println("fez login");
				usuarioLogado = aLogar;
				dManager.setGastosDeUsuario(usuarioLogado.getGastos());
				dManager.setEntradasDeUsuario(usuarioLogado.getEntradas());
				dManager.setContasDeUsuario(usuarioLogado.getContas());

			} else {
				throw new MyMoneyException(DefaultMessages.INV_SENHA_MSG);
			}
		} else {
			throw new AtributoInvalidoException(
					DefaultMessages.USER_N_EXISTE_MSG);
		}
	}

	public String getNomeDoUsuarioLogado() {
		return usuarioLogado.getNome();
	}

	public String getEmailDoUsuarioLogado() {
		return usuarioLogado.getEmail();
	}

	public void logout() throws MyMoneyException {
		verificaUsuarioLogado();
		usuarioLogado.setEntradas(dManager.getListaDeEntradas());
		usuarioLogado.setGastos(dManager.getListaDeGastos());
		usuarioLogado.setContas(dManager.getListaDeContas());
		System.out.println("fez logout");		
		dManager.reset();
		cadastro.gravaCadastro();
		usuarioLogado = null;
	}

	public void cadastraGasto(String id, double valor, String dataStr,
			String categoria, String formaPagamento) throws MyMoneyException {
		verificaUsuarioLogado();
		isFormaPagValido(formaPagamento);
		
		//Date data = DadosUtil.obtemData(dataStr);
		Data data = new Data(dataStr);
		
		if (valor <= 0) {
			throw new AtributoInvalidoException(DefaultMessages.INV_VALOR_MSG
					+ " " + DefaultMessages.INV_ZERO_MSG);
		}

		Gasto gasto = new Gasto(id, valor, data, categoria, formaPagamento);
		dManager.cadastraGasto(gasto);
	}

	private boolean isFormaPagValido(String formaPagamentoStr)
			throws AtributoInvalidoException {
		
		String[] formasPagamentos = { "cheque", "dinheiro", "cartao", "extrato"};
		for (int i = 0; i < formasPagamentos.length; i++) {
			if (formasPagamentos[i].equalsIgnoreCase(formaPagamentoStr)) {
				return true;
			}
		}
		throw new AtributoInvalidoException(DefaultMessages.INV_FORMAPAG_MSG);
	}

	/**
	 * Inicia um conjunto de usuarios para testes.
	 * 
	 * @throws LembreteException
	 */
	public void iniciarUsuarios() throws MyMoneyException {
		cadastro.cadastrar(new Usuario("MAGNO JEFERSON DE SOUZA QUEIROZ",
				"senha1", "magnojs@gmail.com"));
		cadastro.cadastrar(new Usuario("FRANCISCO GOMES DE OLIVEIRA NETO",
				"senha2", "netojin@gmail.com"));
		cadastro.cadastrar(new Usuario("JOAO DA SILVA", "senha3",
				"joao@email.com"));
		cadastro.gravaCadastro();
	}

	public void cadastraEntrada(String id, double valor, String dataStr)
			throws MyMoneyException {
		verificaUsuarioLogado();

		Data data = new Data(dataStr);
		if (valor <= 0) {
			throw new AtributoInvalidoException(DefaultMessages.INV_VALOR_MSG
					+ " " + DefaultMessages.INV_ZERO_MSG);
		}
		Entrada entrada = new Entrada(id, valor, data);
		dManager.cadastraEntrada(entrada);
	}

	private void verificaUsuarioLogado() throws UsuarioException {
		if (usuarioLogado == null) {
			throw new UsuarioException(DefaultMessages.USER_N_LOGADO_MSG);
		}
	}

	public File consultaGasto(String dataInicial, String dataFinal)
			throws MyMoneyException {
		return consultaOperacaoGasto(GASTO_PREFIXO, dataInicial, dataFinal);
//		Date dataIni = DataUtil.obtemData(dataInicial);
//		Date dataFin = DataUtil.obtemData(dataFinal);
//
//		if (dataIni.after(dataFin)) {
//			throw new MyMoneyException("A data inicial deve ser anterior a data final de analise.");
//		}
//		List<Gasto> consulta = dManager.consultaGastosEntre(dataIni, dataFin);
//
//		if (consulta.isEmpty()) {
//			throw new MyMoneyException(DefaultMessages.INV_CONSULTA_MSG);
//			
//		} else {
//			String arquivoDestino = getCaminhoArquivo(GASTO_PREFIXO,
//														dataInicial.replace("/", ""), 
//														dataFinal.replace("/", ""));
//			return RelatorioPrinter.geraArquivo(new ArrayList<Entrada>(),consulta,
//												new ArrayList<ContaaPagar>(), arquivoDestino);
//		}
	}

	private File consultaOperacaoGasto(String operacao, String dataInicial, String dataFinal)
		throws MyMoneyException {
		Data dataIni = new Data(dataInicial);
		Data dataFin = new Data(dataFinal);
		
		if (dataIni.compareTo(dataFin) == 1 ) {
			throw new MyMoneyException("A data inicial deve ser anterior a data final de analise.");
		}
		
		List<Gasto> gastos = new ArrayList<Gasto>();
		List<Entrada> entradas = new ArrayList<Entrada>();
		List<Conta> contas = new ArrayList<Conta>();
		
		if(operacao.equalsIgnoreCase(GASTO_PREFIXO)){
			gastos = dManager.consultaGastosEntre(dataIni, dataFin);
			
		}else if(operacao.equalsIgnoreCase(ENTRADA_PREFIXO)){
			entradas = dManager.consultaEntradasEntre(dataIni, dataFin);
			
		}else if(operacao.equalsIgnoreCase(CONTA_PREFIXO)){
			contas = dManager.consultaContasEntre(dataIni, dataFin);
			
		}else{
			throw new MyMoneyException(DefaultMessages.INV_OPERACAO_MSG);			
		}
		
		String arquivoDestino = getCaminhoArquivo(operacao, dataInicial.replace("/", ""),
													dataFinal.replace("/", ""));
		return RelatorioPrinter.geraArquivo(entradas, gastos, contas, arquivoDestino);
	}

	
	private String getCaminhoArquivo(String prefixoArquivo, String dataInicial,
			String dataFinal) {
		String dirUsuario = RELATORIOS_DIR + usuarioLogado.getNome() + SEP;
		File diretorio = new File(dirUsuario);
		diretorio.mkdirs(); // Cria os diretorios caso eles nao existam.
		String destinoArquivo = dirUsuario + prefixoArquivo + " " + dataInicial
				+ " " + dataFinal;
		return (destinoArquivo.trim())+".txt";
	}

	public File consultaEntrada(String dataInicial, String dataFinal)
			throws MyMoneyException {
		return consultaOperacaoGasto(ENTRADA_PREFIXO, dataInicial, dataFinal);
//		Date dataIni = DataUtil.obtemData(dataInicial);
//		Date dataFin = DataUtil.obtemData(dataFinal);
//
//		if (dataIni.after(dataFin)) {
//			throw new MyMoneyException(
//					"A data inicial deve ser anterior a data final de analise.");
//		}
//		return "";
//		return dManager.consultaEntradasEntre(dataIni, dataFin);
	}

	public void editaGasto(String id, double valor, String aData,
			String categoria, String formaPagamento) throws MyMoneyException {

		verificaUsuarioLogado();
		isFormaPagValido(formaPagamento);

		Data data = new Data(aData);

		if (valor <= 0) {
			throw new AtributoInvalidoException(DefaultMessages.INV_VALOR_MSG
					+ " " + DefaultMessages.INV_ZERO_MSG);
		}

		Gasto gasto = new Gasto(id, valor, data, categoria, formaPagamento);
		// System.out.println("Isso: "+gasto.toString());

		// System.out.println("Id: "+gasto.getId()+ " Data:
		// "+gasto.getData().toLocaleString());

		dManager.editaGasto(gasto);
	}

	public List<String> getGastos() {
		List<String> gastosStr = new ArrayList<String>();
		for (Gasto g : usuarioLogado.getGastos()) {
			gastosStr.add(g.toString());
		}
		return gastosStr;
	}

	public String leBoleto(String nomeArquivo) throws MyMoneyException {
		// LeitorBoleto leitor = new LeitorBoleto(nomeArquivo);
		LeitorExtratoBB leitor = new LeitorExtratoBB(nomeArquivo, dManager.getNextIdGasto(), dManager.getNextIdEntrada());
		dManager.cadastraGastos(leitor.getGastos());
		dManager.cadastraEntradas(leitor.getEntradas());
//		usuarioLogado.addAllGastos(leitor.getGastos());
//		usuarioLogado.addAllEntradas(leitor.getEntradas());
		return "Operacao bem sucedida.";
	}

	public void cadastraConta(String id, double valor, String dataStr,
			String descricaoConta) throws MyMoneyException {
		verificaUsuarioLogado();
		Data dataPagamento = new Data(dataStr);
		if (valor <= 0) {
			throw new AtributoInvalidoException(DefaultMessages.INV_VALOR_MSG
					+ " " + DefaultMessages.INV_ZERO_MSG);
		}
		Conta conta = new Conta(id, valor, dataPagamento,
				descricaoConta);
		dManager.cadastraConta(conta);
	}

	public File geraRelatorio() throws MyMoneyException {
		//Adicionar a data do sistema
		String caminhoRelatorio = getCaminhoArquivo("relatorio", "", "");
		dManager.getListaDeEntradas();
		return RelatorioPrinter.geraArquivo(dManager.getListaDeEntradas(),
				dManager.getListaDeGastos(), dManager.getListaDeContas(), caminhoRelatorio); 
	}

	public File consultaConta(String dataInicial, String dataFinal) throws MyMoneyException {		
		return consultaOperacaoGasto(CONTA_PREFIXO, dataInicial, dataFinal);
	}
	
//	public static void main(String[] args) {
//		//Testes de Date
//		Data data1 = new Data("01/01/09");
//		System.out.println(data1.getYear());
//		System.out.println(data1.toLocaleString());
//		
//		Date data2 = new Date();
//		data2.setDate(1);
//		data2.setMonth(1);
//		data2.setYear(2009);
//		System.out.println(data2.getDate()+"/"+data2.getMonth()+"/"+data2.getYear());
//		System.out.println(data2.toLocaleString());
//
//		Date d = new Date();
//		DateFormat  df = DateFormat.getDateInstance(DateFormat.MEDIUM);
//		System.out.println(df.format(d));
//	}
}
